/*
 *   Copyright (c) 2018. 刘路 All rights reserved
 *   版权所有 刘路 并保留所有权利 2018.
 *   ===============================================================
 *   这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和
 *   使用。不允许对程序代码以任何形式任何目的的再发布。如果项目发布携带作者
 *   认可的特殊 LICENSE 则按照 LICENSE 执行，废除上面内容。请保留原作者信息。
 *   ================================================================
 *   刘路（feedback@zhoyq.com）于 2018. 创建
 *   http://zhoyq.com
 */

package com.zhoyq.helper.lru;

/**
 * 同步LRU列表 同步版近期最少使用算法
 * @author 刘路
 */
public class SyncLRUList extends LRUList {
  @Override
  public synchronized void toHead(LRUAble node) {
    // 如果节点在列表里先移除
    _remove(node);

    // 链接节点到头节点
    node.setNext(head.next);
    node.setPrev(head);
    head.next.setPrev(node);
    head.next = node;
  }
  @Override
  public synchronized void toTail(LRUAble node) {
    // 如果节点在列表里先移除
    _remove(node);

    // 链接节点到尾节点
    node.setPrev(tail.prev);
    node.setNext(tail);
    tail.prev.setNext(node);
    tail.prev = node;

  }

  private final synchronized void _remove(LRUAble node) {
    LRUAble itsPrev, itsNext;
    itsPrev = node.getPrev();
    // 注意：如果节点的前一个链接不是空 那么他的下一个链接也不是空
    if (itsPrev == null){
      return;
    }
    itsNext = node.getNext();
    itsPrev.setNext(itsNext);
    itsNext.setPrev(itsPrev);
  }
  @Override
  public final synchronized LRUAble remove(LRUAble node) {
    _remove(node);
    node.setNext((LRUAble) null);
    node.setPrev((LRUAble) null);
    return node;
  }
  @Override
  public final synchronized LRUAble getTail() {
    LRUAble prev = tail.prev;
    return (prev == head) ? null : prev;
  }
  @Override
  public final synchronized LRUAble getHead() {
    LRUAble next = head.next;
    return (next == tail) ? null : next;
  }
  @Override
  public final synchronized LRUAble removeTail() {
    if (tail.prev != head){
      return remove(tail.prev);
    }
    return null;
  }
  @Override
  public final synchronized LRUAble getNext(LRUAble node) {
    LRUAble next = node.getNext();
    return ((next == tail) || (next == head)) ? null : next;
  }
  @Override
  public final synchronized LRUAble getPrev(LRUAble node) {
    LRUAble prev = node.getPrev();
    return ((prev == tail) || (prev == head)) ? null : prev;
  }

}
